package cn.itsource.hrm.service.impl;

import cn.hutool.core.util.ZipUtil;

import cn.itsource.hrm.clinet.StaticPageClient;
import cn.itsource.hrm.client.FileClient;

import cn.itsource.hrm.client.RedisClient;

import cn.itsource.hrm.controller.vo.CourseTypeVo;
import cn.itsource.hrm.domain.CourseType;
import cn.itsource.hrm.mapper.CourseTypeMapper;
import cn.itsource.hrm.service.ICourseTypeService;
import cn.itsource.hrm.util.AjaxResult;
import cn.itsource.hrm.util.StrUtils;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;


import java.io.*;

import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author jinhui
 * @since 2020-05-22
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {
    private final String COURSE_TYPE_KEY = "COURSETYPES:TREE";

    private Logger logger = LoggerFactory.getLogger(CourseTypeServiceImpl.class);
    private static final String EXCHANG_NAME="hrm-couseTypes2";

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private FileClient fileClient;

    @Autowired
    private StaticPageClient staticPageClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Override
    public List<CourseTypeVo> loadCrumbs(Long courseTypeId) {
        CourseType courseType = baseMapper.selectById(courseTypeId);
        String path = courseType.getPath();
        //获取到类型级别id
        List<Long> ids = StrUtils.splitStr2LongArr(path.substring(1), "\\.");
        List<CourseTypeVo> courseTypeVos= new ArrayList<>();
        CourseTypeVo courseTypeVo=null;
        for(Long id:ids){
            courseTypeVo = new CourseTypeVo();
            //查询出当前类型
            CourseType type = baseMapper.selectById(id);
            courseTypeVo.setCourseType(type);
            //查询出当前类型的其他类型
            List<CourseType> courseTypeList = baseMapper.selectList(new QueryWrapper<CourseType>().eq("pid", type.getPid()).ne("id", type.getId()));
            courseTypeVo.setOtherTypes(courseTypeList);
            //将当前类型和当前类型的其他类型添加到集合中
            courseTypeVos.add(courseTypeVo);
        }
        return courseTypeVos;
    }

    @Override
    public void staticHomePage() throws Exception {
        //上传打包后的模板到，返回一个fileid
        //获取模板路径
        //打包模板
        String classPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        String srcPath = classPath + "templates";
        String zipPath = classPath + "static.zip";
        ZipUtil.zip(srcPath, zipPath);
        //上传模板到fastdfs
        File f = new File(zipPath);
        InputStream input = null;
        OutputStream os = null;
            FileItem fileItem = new DiskFileItem("file", Files.probeContentType(f.toPath()), false, f.getName(), (int) f.length(), f.getParentFile());
            input = new FileInputStream(f);
            os = fileItem.getOutputStream();
            IOUtils.copy(input, os);
            input.close();
            os.close();
            MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
            AjaxResult result = fileClient.upload(multipartFile);
        //调用文件服务,调用页面静态化服务将模板拉取下来与数据组装，上传到fastdfs
        //模拟数据
        Map<String, Object> data = new HashMap<>();
        //添加数据
        data.put("courseTypes",loadCourseTypeTree());
        //页面静态化
        AjaxResult result1 = staticPageClient.staticPage((String) result.getResultObj(), data);
        String fileID = result1.getResultObj().toString();
        //将fileid作为消息发送到mq中
        rabbitTemplate.convertAndSend(EXCHANG_NAME,"page.couse.home",fileID);
    }
    @Override
    public List<CourseType> loadCourseTypeTree() {
//        //获取课程类型前，先判断缓存中是否存在
//        String courseTypeKeyStr = redisClient.get("COURSE_TYPE_KEY");
//        if (!StringUtils.isEmpty(courseTypeKeyStr)){
//            //存在则直接将缓存中的数据转换为java对象返回
//            List<CourseType> courseTypeList = JSONArray.parseArray(courseTypeKeyStr, CourseType.class);
//            return courseTypeList;
//        }
//        //不存在，查询数据库后，将数据转换为json对象做缓存后，再返回
//        else {
//            List<CourseType> typeList = loadTypeLoopAndMap();
//            String CourseTypesJson = JSONArray.toJSONString(typeList);
//            redisClient.set("COURSE_TYPE_KEY",CourseTypesJson);
//
//            return typeList;
//        }
        //先判断缓存中的数据是否存在
        String courseTypesStr = redisClient.get(COURSE_TYPE_KEY);
        logger.debug("从缓存中查询............");

        if (!StringUtils.isEmpty(courseTypesStr)) {
            //如果存在，则直接将数据返回，将json字符串转为List对象
            List<CourseType> courseTypes = JSONArray.parseArray(courseTypesStr, CourseType.class);
            return courseTypes;
        }
        //如果不存在，则查询数据库，将数据缓存后再返回
        List<CourseType> courseTypes = loadTypeLoopAndMap();
        logger.debug("从数据库中查询......");
        //将List对象转为json字符串
        String courseTypeJSON = JSONArray.toJSONString(courseTypes);
        redisClient.set(COURSE_TYPE_KEY, courseTypeJSON);
        return courseTypes;


    }

    //使用循环加map容器的方式
    public List<CourseType> loadTypeLoopAndMap() {
//        //1.查询出所有类型
//        List<CourseType> allCourseTypeList = baseMapper.selectList(null);
//        //2.创建一个容器装所有顶级父类型
//        List<CourseType> courseTypeList=new ArrayList<>();
//        //3.创建一个map容器装所有类型,key为类型id，value为类型
//        Map<Long,CourseType> courseTypeMap=new HashMap<>();
//        for (CourseType courseType:allCourseTypeList){
//            courseTypeMap.put(courseType.getId(),courseType);
//        }
//        //4.循环的出所有父类型并放入容器
//        for (CourseType courseType:allCourseTypeList){
//            //如果类型的pid为0，则是顶级父类型
//            if(courseType.getPid()==0){
//                courseTypeList.add(courseType);
//            }
//            //如果类型的pid不为0，则是不是顶级父类型
//            else {
//                //通过子类pid找到父类型
//                CourseType parentType = courseTypeMap.get(courseType.getPid());
//                parentType.getChildren().add(courseType);
//            }
//        }
//        return courseTypeList;
        //1、查询所有的课程类型
        List<CourseType> courseTypesList = baseMapper.selectList(null);

        //2、创建一个容器存储所有的一级类型
        List<CourseType> firstCourseTypes = new ArrayList<>();

        //3、创建一个Map容器存储所有类型,key是类型的id，value为类型对象
        Map<Long, CourseType> courseTypeMap = new HashMap<>();
        for (CourseType courseType : courseTypesList) {
            courseTypeMap.put(courseType.getId(), courseType);
        }

        //4、遍历所有的课程类型，如果当前类型没有父类型，则放入到一级类型的集合中
        for (CourseType courseType : courseTypesList) {
            if (courseType.getPid() == 0) {
                firstCourseTypes.add(courseType);
            } else {
                //5、如果当前类型有父类型，则找到对应的父类型，添加父类型的children中
                //找对应的父类型
                CourseType parentType = courseTypeMap.get(courseType.getPid());
                parentType.getChildren().add(courseType);
            }
        }

        return firstCourseTypes;

    }

    //定义一个递归方法，自动去组装所有当前类型下的子类型
    private List<CourseType> loadTypeRecursion(Long id) {
        List<CourseType> courseTypeList = baseMapper.selectList(new QueryWrapper<CourseType>().eq("pid", id));
        //出口
        if (courseTypeList == null || courseTypeList.isEmpty()) {
            return null;
        }
        //遍历当前类型
        for (CourseType courseType : courseTypeList) {
            //查询出当前类型的子类型，并设置
            List<CourseType> chilrdren = loadTypeRecursion(courseType.getId());
            courseType.setChildren(chilrdren);
        }
        //此时的类型中就包含了子类型
        return courseTypeList;
    }

    //使用嵌套循环的方式组装父类型下的所有子类型
    public List<CourseType> loadTypeLoop() {
        //1.查询出所有类型
        List<CourseType> allCourseTypeList = baseMapper.selectList(null);
        //2.创建一个容器装所有顶级父类型
        List<CourseType> courseTypeList = new ArrayList<>();
        //3.循环的出所有父类型并放入容器
        for (CourseType courseType : allCourseTypeList) {
            //如果类型的pid为0，则是顶级父类型
            if (courseType.getPid() == 0) {
                courseTypeList.add(courseType);
            }
            //如果类型的pid不为0，则是不是顶级父类型
            else {
                for (CourseType allcourseType : allCourseTypeList) {
                    if (courseType.getPid().equals(allcourseType.getId())) {
                        allcourseType.getChildren().add(courseType);
                        break;
                    }

                }
            }
        }
        return courseTypeList;
    }

    @Override
    public boolean save(CourseType entity) {
        super.save(entity);
        syncOpr();
        return false;
    }

    @Override
    public boolean removeById(Serializable id) {
        super.removeById(id);
        syncOpr();
        return false;
    }

    @Override
    public boolean updateById(CourseType entity) {
        super.updateById(entity);
        syncOpr();
        return false;
    }
    private void syncOpr(){
        //增删改之后重新获取最新数据放入缓存并重新页面静态化
        List<CourseType> courseTypes = loadTypeLoopAndMap();
        String courseTypeJSON = JSONArray.toJSONString(courseTypes);
        redisClient.set(COURSE_TYPE_KEY, courseTypeJSON);
        try {
            staticHomePage();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
